////////////////////////////TCF/////////////////////////////
// TPC Coherent Fit (TCF)                                 //
// Author: Xianguo Lu, lu.xianguo@gmail.com               //
// Reference: Xianguo Lu, "Exploring the performance      //
// limits of the ALICE Time Projection Chamber and        //
// Transition Radiation Detector for measuring identified //
// hadron production at the LHC", dissertation at the     //
// University of Heidelberg (2013).                       //
////////////////////////////////////////////////////////////

#ifndef _DEDXGAUSN_H_
#define _DEDXGAUSN_H_

#include "BaseUtils.h"
#include "TPCHist.h"
#include "TTreeStream.h"

class dEdxGausN
{
 private:
  ~dEdxGausN(){}

 public: 
  enum bbopt{
    kmBB = 1,
    kRawALEPH = 2,
    kBBXing = 4,
    kLund = 16
  };

  enum TYPEID{
    kPROTON,
    kPION,
    kKAON,
    kELECTRON
  };

  //==================================================================================
  //                              controls
  //==================================================================================
 public:
  static Double_t MinResolution(){return fMinResolution;}
  static Double_t MaxResolution(){return fMaxResolution;}
  static Double_t IniResolution(){ return fIniResolution;}

  static Int_t LastfithIter(){return 5;}  

  static Int_t Ntype(){ return fNtype;}

  static Int_t NparType() { return fNparType;}
  static BaseUtils::FFunc GausFunc(){ return fGausFunc;}

  static Int_t BBOpt(){return fBBopt;}
  static Int_t NparBB(){return fNparBB;}
  static const Int_t NparBasicBB(){ return 5;}
  static const Double_t * IniBBpar(){ return fIniBBpar;}
  static BaseUtils::FFunc BBFunc(){return fBBFunc;}

  static Int_t NparSignalShift();
  static Bool_t IsSignalShift(){ return fkSignalShift;}

 private:
  static Double_t fMinResolution;
  static Double_t fMaxResolution;
  static Double_t fIniResolution;

  static Int_t fNtype;

  static Int_t fNparType;
  static BaseUtils::FFunc fGausFunc;

  static Int_t fBBopt;
  static Bool_t fkEnergyLossCorrection;
  static Bool_t fkSignalShift;
  static BaseUtils::FFunc fBBFunc;
  static Int_t fNparBB;
  static Double_t *fIniBBpar;


  //==================================================================================
  //                               initialization
  //==================================================================================
 public:
  static void Ini();
  
 private:
  
  //==================================================================================
  //                                Parameters
  //==================================================================================
 public:
  static Int_t Npar(){return NparType()*Ntype();}

  static void ResetIfixed(Bool_t pfix[]);
  static Int_t SetIfixAllBB(Bool_t pfix[], const Bool_t kfix);
  static Int_t SetIfixExtraBB(Bool_t pfix[], const Bool_t kfix);
  static void SetMean(const Double_t xx, const Double_t bbpar[], Double_t pregauspar[], Int_t *neworder=0x0, const Bool_t kprint=0);
  static void ToGausPar(const Double_t *prepar, Double_t *gauspar, const Double_t *prelowerr=0x0, const Double_t *prehigherr=0x0, Double_t *gauslowerr=0x0, Double_t *gaushigherr=0x0);

 private:  
  static void SetGausErr(Double_t * gauserr, const Double_t * preerr, const Double_t * prepar);
 
  //==================================================================================
  //                             functions
  //==================================================================================
 public: 
  static Double_t Func(const Double_t *xx, const Double_t *raw);
  static Double_t GetMean(const Double_t xx, const Double_t mass, const Double_t *bbpar, const Bool_t kprint=0);
  static Double_t ALICEBetheBlochSolid(const Double_t bg);
  static Double_t BetheBlochXing(const Double_t *xx, const Double_t *par);
  static Double_t BetheBlochModified(const Double_t *xx, const Double_t *par);
  static Double_t FindCrossingLog10P(const Double_t* par, BaseUtils::FFunc func, const Double_t m1, const Double_t m2);
  static Double_t FindCrossingBetheBlochModified(const Double_t *par, const Double_t m1, const Double_t m2);

  static void Geta2a3FromKaonCrossings(Double_t &a2, Double_t &a3, const Double_t a1, const Double_t croPi, const Double_t croProton);
  static Double_t RawAleph(const Double_t *xx, const Double_t *par);
  static Double_t Lund(const Double_t *xx, const Double_t *par);

 private:  
  static void SetBetheBlochXingKs(Double_t kk[], const Double_t a1, const Double_t pAB, const Double_t mA, const Double_t mB);
  
  //==================================================================================
  //                             algorithms
  //==================================================================================
 public:
  static void Swap(const Double_t xx, const Int_t targetip, Double_t pars[], const Int_t oldid[], const Int_t newid[]);
  static void GetInvMap(const Int_t order[], Int_t invmap[]);

 private:  
  static void GetInvMap(const Int_t nn, const Int_t order[], Int_t invmap[]);
  
  //==================================================================================
  //                               kinematics
  //==================================================================================
 public:
  static Double_t Mass(const Int_t id);
  static const Char_t * ParticleName(const Int_t id);

  static Double_t Mproton   (){ return  0.938272;}
  static Double_t Mpion     (){ return  0.139570;}
  static Double_t Mkaon     (){ return  0.493677;}
  static Double_t Melectron (){ return  5.109989e-04;}
  
 private:  
  
  //==================================================================================
  //                            histogram
  //==================================================================================
 public:

 private:

  //===================================================================================
  //===================================================================================

 private:  
  
  //==================================================================================
  //                            outputs
  //==================================================================================
 public:
  static void SavePar(TTreeSRedirector * stream, const TString tn, Double_t *totalyield, Double_t *yields, Double_t *pars, Double_t *lowerrs, Double_t *higherrs, const Int_t order[], Double_t *outpar, Double_t *outlowerr, Double_t *outhigherr, Int_t *orderinv=0x0);
  static TH1D* dEdxFit(TGraphErrors * gr, const TString hname, const Bool_t kfailexit, const Double_t *inipar, const Double_t *lows=0x0, const Double_t *highs=0x0, const Double_t maxchi2=1e10);
  static void DrawTF1(const Int_t id, const TString tag,  const Double_t pars[], const Int_t col, TList *ll, FILE *log=0x0);

 private:  
  static void Print();

  //==================================================================================
  //                            end
  //==================================================================================

  ClassDef(dEdxGausN,3);
};

#endif

